
#define RUNTIME_DBG_LVL 0
#define _GNU_SOURCE
/* #include <pthreadalt.h> */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <dbg.h>
#include <dbg/ptest.h>
// #include <ddblk/syslock.h>
#include <ddblk/locks.h>
#include <ddblk/locks2apds.h>
#include "dblk_test.h"
#include "dblk_perftest.h"

#define TEST_NR		(1000000)
#define TEST_THREADNR	(HDEF_NATIVE_CPU_NR)

#define LOCK_MAXFUTURES	(16)
static TLS_INITIAL apdsfuture_t apdsfuture_tls[LOCK_MAXFUTURES]; 
static TLS_INITIAL hword_t apdsfuture_cnt; 
static TLS_INITIAL slist_t *apdsfuture_head;
SAI apdsfuture_t *apfsdsfuture_get_tls(){
	if (!apdsfuture_head){
		ASSERT(apdsfuture_cnt < LOCK_MAXFUTURES);
		return &apdsfuture_tls[apdsfuture_cnt++];
	}
	slist_t *ret = apdsfuture_head;
	apdsfuture_head = ret->next;
	return (apdsfuture_t *)ret;
}
SAI void apfsdsfuture_ret_tls(apdsfuture_t *future){
	slist_t *node = (slist_t *)future;
	node->next = apdsfuture_head;
	apdsfuture_head = node;
}

LOCKS2APDS(mutex, apdsmutex, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(pspin, apdspspin, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)

LOCKS2APDS(spin, apdsspin, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(ticket, apdsticket, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(futex_spin, futex_apdsspin, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(futex_ticket, futex_apdsticket, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(yield_spin, yield_apdsspin, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(yield_ticket, yield_apdsticket, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)

DEF_LOCKNODE_ALIGNMALLOC(alignlknode, HDEF_CACHE_LINE_BYTES)
DEF_NLOCK(clh, clh, OUFUN_OF(spin_wait), OUFUN_OF(alignlknode))
DEF_NLOCK(clh, bounded_clh, OUFUN_OF(spin_wait_bounded), OUFUN_OF(alignlknode))
DEF_NLOCK(clh, futex_clh, OUFUN_OF(futex_wait), OUFUN_OF(alignlknode))
DEF_NLOCK(clh, yield_clh, OUFUN_OF(schedyield_wait), OUFUN_OF(alignlknode))

DEF_NLOCK(mcs, mcs, OUFUN_OF(spin_wait), OUFUN_OF(alignlknode))
DEF_NLOCK(mcs, bounded_mcs, OUFUN_OF(spin_wait_bounded), OUFUN_OF(alignlknode))
DEF_NLOCK(mcs, futex_mcs, OUFUN_OF(futex_wait), OUFUN_OF(alignlknode))
DEF_NLOCK(mcs, yield_mcs, OUFUN_OF(schedyield_wait), OUFUN_OF(alignlknode))

LOCKS2APDS(clh, apdsclh, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(mcs, apdsmcs, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(futex_clh, futex_apdsclh, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(futex_mcs, futex_apdsmcs, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(yield_clh, yield_apdsclh, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)
LOCKS2APDS(yield_mcs, yield_apdsmcs, apfsdsfuture_get_tls, apfsdsfuture_ret_tls)



DEF_TEST_TYPE(apdsmutex, fetch_add, TEST_NR)
DEF_TEST_TYPE(apdspspin, fetch_add, TEST_NR)

DEF_TEST_TYPE(apdsspin, fetch_add, TEST_NR)
// DEF_TEST_TYPE(futex_apdsspin, fetch_add, TEST_NR)
DEF_TEST_TYPE(yield_apdsspin, fetch_add, TEST_NR)

DEF_TEST_TYPE(apdsticket, fetch_add, TEST_NR)
// DEF_TEST_TYPE(futex_apdsticket, fetch_add, TEST_NR)
DEF_TEST_TYPE(yield_apdsticket, fetch_add, TEST_NR)

DEF_TEST_TYPE(apdsclh, fetch_add, TEST_NR)
// DEF_TEST_TYPE(futex_apdsclh, fetch_add, TEST_NR)
DEF_TEST_TYPE(yield_apdsclh, fetch_add, TEST_NR)

DEF_TEST_TYPE(apdsmcs, fetch_add, TEST_NR)
// DEF_TEST_TYPE(futex_apdsmcs, fetch_add, TEST_NR)
DEF_TEST_TYPE(yield_apdsmcs, fetch_add, TEST_NR)
/* 锁性能测试, 转换成统一的apds接口 */
int main(){
	test_apdsmutex(TEST_THREADNR);
	printf("%lu\n", ptc);
	test_apdspspin(TEST_THREADNR);
	printf("%lu\n", ptc);

	test_apdsspin(TEST_THREADNR);
	printf("%lu\n", ptc);
	// test_futex_apdsspin(TEST_THREADNR);
	// printf("%lu\n", ptc);
	test_yield_apdsspin(TEST_THREADNR);
	printf("%lu\n", ptc);

	test_apdsticket(TEST_THREADNR);
	printf("%lu\n", ptc);
	// test_futex_apdsticket(TEST_THREADNR);
	// printf("%lu\n", ptc);
	test_yield_apdsticket(TEST_THREADNR);
	printf("%lu\n", ptc);

	test_apdsclh(TEST_THREADNR);
	printf("%lu\n", ptc);
	// test_futex_apdsclh(TEST_THREADNR);
	// printf("%lu\n", ptc);
	test_yield_apdsclh(TEST_THREADNR);
	printf("%lu\n", ptc);

	test_apdsmcs(TEST_THREADNR);
	printf("%lu\n", ptc);
	// test_futex_apdsmcs(TEST_THREADNR);
	// printf("%lu\n", ptc);
	test_yield_apdsmcs(TEST_THREADNR);
	printf("%lu\n", ptc);
	return 0;
}
